package com.anji.hyperneat.modular;

/**
 * Input Mapper intended for inputting node coordinates.
 * @author slusk
 *
 */
public class CoordinateInputMapper implements ICppnInputMapper {

	protected float vals[];
	protected int layer;
	protected int[][] layerDimensions;
	
	/** 
	 * Constructor.
	 * @param layerDimensions 2-d array describing the dimensions of the network; format: layerDimensions[layer][dimension]
	 * @param numDimensions The number of dimensions per layer; this should be the same for every layer, the layers should have been cast to a set number of dimensions at creation.
	 */
	public CoordinateInputMapper(int[][] layerDimensions, int numDimensions) {
		vals = new float[numDimensions];
		this.layerDimensions = layerDimensions;
	}

	@Override
	public float[] getInputs() {
		return vals;
	}

	@Override
	public int getNumInputs() {
		return vals.length;
	}

	
	/**
	 * Popoulate this mappers input values (coordinates), based on the current layer (layer is necessary to provide proper normalization).
	 * @param layer The layer for this set of coordinates.
	 * @param vals The coordinates 
	 */
	public void populateValues(int layer, int[] vals) {
		if (vals.length != this.vals.length) throw new IllegalArgumentException("Input array size does not match size specified at construction time.");
		this.layer = layer;
		int idx = 0;
		for (int val : vals) {
			this.vals[idx++] = val;
		}
	}

	@Override
	public float[] getNormalizedInputs() {
		float[] norms = new float[vals.length];
		for (int i = 0; i < norms.length; i++) {
			if (layerDimensions[layer][i] > 1) 
				norms[i] = ( vals[i] / (layerDimensions[layer][i] - 1) ) * 2 - 1;
			else
				norms[i] = 0.0f;
		}
		return norms;
	}

}
